//
//  CBDAddressBookManager.m
//  addressBookTest
//
//  Created by sheepyellow on 15/8/22.
//  Copyright (c) 2015年 sheepyellow. All rights reserved.
//

#import "CBDAddressBookManager.h"
#import "MUCAddressBookModel.h"
@interface MUCAddressBookNotification()

@end

@implementation MUCAddressBookNotification

-(BOOL)isEqualToNotification:(MUCAddressBookNotification*)object
{
    if(!object)
        return NO;
    if(object.identifer==nil)
        return NO;
    if(object.selector==nil)
        return NO;
    if(object.target==nil)
        return NO;
    if(![object isKindOfClass:[self class]])
        return NO;
    if(self==object)
        return YES;
    if([self isEqual:object])
        return YES;
    if([self.identifer isEqualToString:object.identifer]&&[self.target isEqualToSet:object.target]&&[NSStringFromSelector(self.selector) isEqualToString:NSStringFromSelector(object.selector)])
        return YES;
    return NO;
}

@end

@interface MUCAddressBookManager()

@property(assign, nonatomic)ABAddressBookRef addressBook;
@property(assign, nonatomic)CFErrorRef  error;
@property(assign, nonatomic)CFMutableDictionaryRef dictionaryRef;
@property(strong, nonatomic)NSMutableArray*   notificationArray;
@property(strong, nonatomic)NSMutableArray* recordArray;
@end

static MUCAddressBookManager* g_addressBookManager=nil;
@implementation MUCAddressBookManager

+(instancetype)shareInstance
{
    dispatch_once_t predicate=0;
    dispatch_once(&predicate, ^{
        g_addressBookManager=[[MUCAddressBookManager alloc] init];
       
    });

    return g_addressBookManager;
}

void addressBookChanged(ABAddressBookRef addressBook, CFDictionaryRef info, void* context)
{
    NSLog(@"Address Book Changed");
    MUCAddressBookManager* manaer=objc_unretainedObject(context);
    NSDictionary* dict=nil;
    if(info)
    {
        CFDictionaryGetCount(info);
        dict=CFBridgingRelease(info);
    }

    [manaer updateAddressBook:dict];
}

-(id)init
{
    if(!g_addressBookManager)
    {
        self=[super init];
        if(self)
        {
            self.dictionaryRef=CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, NULL);
            self.notificationArray=[[NSMutableArray alloc] init];
            self.recordArray=[[NSMutableArray alloc] init];
            CFErrorRef error;
            self.addressBook=ABAddressBookCreateWithOptions(NULL,&error);
            if(error)
            {
                self.error=error;
                CFRelease(error);

            }
            else
                ABAddressBookRegisterExternalChangeCallback(self.addressBook, addressBookChanged, (void*)CFBridgingRetain(self));
            
        }
        return self;
    }
    else
    {

        @throw([[NSException alloc] initWithName:@"MUCAddressBookManager init" reason:@"please User shareInstance initial Object" userInfo:nil]);
    }
}

-(void)dealloc
{
    CFRelease(self.addressBook);
    CFRelease(self.error);
    CFRelease(self.dictionaryRef);
    ABAddressBookRegisterExternalChangeCallback(self.addressBook, addressBookChanged, (void*)CFBridgingRetain(self));
}

#pragma mark - setter and getter


-(void)setDictionaryRef:(CFMutableDictionaryRef)dictionaryRef
{
    if(_dictionaryRef)
        CFRelease(_dictionaryRef);
    _dictionaryRef=CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, dictionaryRef);;
}

+(ABAuthorizationStatus)authStatus
{
    ABAuthorizationStatus tempStatus=ABAddressBookGetAuthorizationStatus();
    return tempStatus;
}

-(NSArray*)records
{
    NSArray* array=[self.recordArray copy];
    return array;
}

#pragma mark - function

-(BOOL)accessAddressBook
{
    __block BOOL bret=NO;
    dispatch_semaphore_t semaphore=dispatch_semaphore_create(0);
    dispatch_time_t timeout=dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC*10);
    ABAddressBookRequestAccessWithCompletion(self.addressBook, ^(bool granted, CFErrorRef error) {
        if(granted)
        {
            bret=YES;
            [self.recordArray removeAllObjects];
        }
        else
        {
            bret=NO;
            UIAlertView* alert=[[UIAlertView alloc] initWithTitle:@"温馨提示" message:@"通讯录读取失败！" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
            [alert show];
        }
        dispatch_semaphore_signal(semaphore);
            
    });
    dispatch_semaphore_wait(semaphore, timeout);
    if([self.class authStatus]==kABAuthorizationStatusAuthorized)
    {
        CFArrayRef result=ABAddressBookCopyArrayOfAllPeople(self.addressBook);
        CFIndex nPeople=ABAddressBookGetPersonCount(self.addressBook);
        
        for (int i=0; i<nPeople; i++)
        {
            MUCAddressBookModel* model=[[MUCAddressBookModel alloc] init];
            
            ABRecordRef record= CFArrayGetValueAtIndex(result, i);
            if(!record)
                continue;
            CFTypeRef abfirstname = ABRecordCopyValue(record, kABPersonFirstNameProperty);
            CFTypeRef abLastName = ABRecordCopyValue(record, kABPersonLastNameProperty);
            NSString *firstNameString = CFBridgingRelease(abfirstname);
            NSString *lastNameString = CFBridgingRelease(abLastName);
            model.firstName=firstNameString;
            model.lastName=lastNameString;
            model.modelId = (NSInteger)ABRecordGetRecordID(record);
            
            ABPropertyID multiProperties[] = {
                kABPersonPhoneProperty,
                kABPersonEmailProperty
            };
            NSInteger multiPropertiesTotal = sizeof(multiProperties) / sizeof(ABPropertyID);
            for (NSInteger j = 0; j < multiPropertiesTotal; j++) {
                ABPropertyID property = multiProperties[j];
                ABMultiValueRef valuesRef = ABRecordCopyValue(record, property);
                NSInteger valuesCount = 0;
                if (valuesRef != nil) valuesCount = ABMultiValueGetCount(valuesRef);
                
                if (valuesCount == 0) {
                    CFRelease(valuesRef);
                    continue;
                }
                //获取电话号码和email
                for (NSInteger k = 0; k < valuesCount; k++) {
                    CFTypeRef value = ABMultiValueCopyValueAtIndex(valuesRef, k);
                    switch (j) {
                        case 0: {// Phone number
                            model.phoneNumber = (__bridge NSString*)value;
                            break;
                        }
                        case 1: {// Email

                            break;
                        }
                    }
                    CFRelease(value);
                }
                CFRelease(valuesRef);
            }
            [self.recordArray addObject:model];
//            if (abLastName) CFRelease(abLastName);
//            if (abfirstname) CFRelease(abfirstname);
//            if(record) CFRelease(record);
        }
            
        
        CFRelease(result);
    }
    return bret;
}

-(void)updateAddressBook:(id)object
{
    for (MUCAddressBookNotification* subject in self.succssObservers)
    {

        if([subject.target respondsToSelector:subject.selector])
        {
            dispatch_async(dispatch_get_main_queue(), ^{
                [subject.target performSelector:subject.selector withObject:object];
            });
            
        }
    }
}

-(NSInteger)indexdOfObject:(MUCAddressBookNotification*)object
{
    NSInteger nret=NSNotFound;
    int i=0;
    for (MUCAddressBookNotification* notification in self.notificationArray)
    {
        if([notification isEqualToNotification:object])
        {
            nret=i;
            break;
        }
    }
    return nret;
}

-(void)safeAddObject:(MUCAddressBookNotification*)object
{
    NSInteger nIndex=[self indexdOfObject:object];
    if(nIndex==NSNotFound)
    {
        [self.notificationArray addObject:object];
    }
}

-(void)removeObject:(MUCAddressBookNotification*)object
{
    if(!object)
        return;
    if([object isKindOfClass:[MUCAddressBookNotification class]])
        return;
    NSInteger nIndex=[self indexdOfObject:object];
    [self.notificationArray removeObjectAtIndex:nIndex];
}

-(void)addUpdateSuccessObserver:(id)observer selector:(SEL)aSelector
{
    [self addObserver:observer selector:aSelector name:kADDRESSBOOKUPDATE_SUCCESS];
}

-(void)addupdateFaildObserver:(id)observer selector:(SEL)aSelector
{
    [self addObserver:observer selector:aSelector name:kADDRESSBOOKUPDATE_ERROR];
}

-(void)removeUpdateSuccessObserver:(id)observer selector:(SEL)aSelector
{
    [self removeObserver:observer selector:aSelector name:kADDRESSBOOKUPDATE_SUCCESS];
}

-(void)removeUpdateFaildObseerver:(id)observer selector:(SEL)aSelector
{
    [self removeObserver:observer selector:aSelector name:kADDRESSBOOKUPDATE_ERROR];
}

-(void)removeAllObserver:(id)observer selector:(SEL)aSelector
{
    [self removeUpdateSuccessObserver:observer selector:aSelector];
    [self removeUpdateFaildObseerver:observer selector:aSelector];
}

- (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName
{
    MUCAddressBookNotification* notification=[[MUCAddressBookNotification alloc] init];
    notification.target=observer;
    notification.selector=aSelector;
    notification.identifer=aName;
    
    [self safeAddObject:notification];
}

-(void)removeObserver:(id)observer selector:(SEL)aSelector name:(NSString*)aName
{
    MUCAddressBookNotification* notification=[[MUCAddressBookNotification alloc] init];
    notification.target=observer;
    notification.selector=aSelector;
    notification.identifer=aName;
    
    [self removeObject:notification];
}

-(NSArray*)succssObservers
{
    NSArray* retArray=nil;
    NSMutableArray* tempArray=[[NSMutableArray alloc] init];
    for (MUCAddressBookNotification* object in self.notificationArray) {
        if([object.identifer isEqualToString:kADDRESSBOOKUPDATE_SUCCESS])
        {
            [tempArray addObject:object];
        }
    }
    if(tempArray.count>0)
    {
        retArray=[tempArray copy];
    }
    return retArray;
}


@end
